package com.mornd.gulimall.member.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mornd.gulimall.apis.member.to.MemberLoginTo;
import com.mornd.gulimall.apis.member.to.MemberRegistTo;
import com.mornd.gulimall.common.core.constant.enums.UserStatus;
import com.mornd.gulimall.common.core.entity.SessionUser;
import com.mornd.gulimall.common.core.exception.ExistedException;
import com.mornd.gulimall.common.core.exception.LoginFailException;
import com.mornd.gulimall.common.core.utils.Validator;
import com.mornd.gulimall.member.entity.Member;
import com.mornd.gulimall.member.entity.MemberLevel;
import com.mornd.gulimall.member.mapper.MemberMapper;
import com.mornd.gulimall.member.service.IMemberLevelService;
import com.mornd.gulimall.member.service.IMemberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * <p>
 * 会员 服务实现类
 * </p>
 *
 * @author mornd
 * @since 2023-07-31
 */
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements IMemberService {
    @Resource
    private IMemberLevelService memberLevelService;
    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public void regist(MemberRegistTo to) {

        checkPhoneUnique(to.getPhone());
        checkUsernameUnique(to.getUsername());

        Member member = new Member();
        MemberLevel defaultLevel = memberLevelService.getOne(Wrappers.<MemberLevel>lambdaQuery().eq(MemberLevel::getDefaultStatus, 1).last(" limit 1"));

        if (defaultLevel != null) {
            member.setLevelId(defaultLevel.getId());
        }

        member.setUsername(to.getUsername());
        member.setNickname(member.getNickname());
        member.setCreateTime(LocalDateTime.now());
        member.setMobile(to.getPhone());
        member.setStatus(UserStatus.NORMAL.ordinal());

        // 密码加密
        String encodedPassword = bCryptPasswordEncoder.encode(to.getPassword());
        member.setPassword(encodedPassword);

        super.save(member);
    }

    @Override
    public void checkPhoneUnique(String phone) {
        long count = super.count(Wrappers.<Member>lambdaQuery().eq(Member::getMobile, phone));
        if (count > 0) {
            throw new ExistedException("手机号已存在");
        }
    }

    @Override
    public void checkUsernameUnique(String username) {
        long count = super.count(Wrappers.<Member>lambdaQuery().eq(Member::getUsername, username));
        if (count > 0) {
            throw new ExistedException("用户名已存在");
        }
    }

    @Override
    public SessionUser login(MemberLoginTo to) {
        // 用户名或者密码登录
        boolean phone = Validator.isValidPhoneNumber(to.getAccount());

        LambdaQueryWrapper<Member> qw = Wrappers.<Member>lambdaQuery().eq(Member::getUsername, to.getAccount());
        if (phone) {
            // 账号匹配手机号，就加上手机号条件查询
            qw.or().eq(Member::getMobile, to.getAccount());
        }

        Member dbMember = super.getOne(qw);
        if (dbMember == null) {
            throw new LoginFailException("用户不存在");
        }

        boolean matches = bCryptPasswordEncoder.matches(to.getPassword(), dbMember.getPassword());
        if (!matches) {
            throw new LoginFailException("密码错误");
        }

        if (dbMember.getStatus() != null && dbMember.getStatus() == UserStatus.LOCKED.ordinal()) {
            throw new LoginFailException("该账户已被锁定");
        }

        SessionUser sessionUser = new SessionUser();
        BeanUtils.copyProperties(dbMember, sessionUser);

        return sessionUser;
    }
}
